package com.szp.lg.blog.datasource;

import com.alibaba.fastjson.JSON;
import com.szp.lg.blog.config.props.DataSourceProps;
import com.szp.lg.blog.config.props.ZkProps;
import com.szp.lg.blog.constant.ConstantDbZkPath;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.cache.ChildData;
import org.apache.curator.framework.recipes.cache.NodeCache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

@Configuration
@EnableConfigurationProperties(DataSourceProps.class)
public class DataSourceConfig implements InitializingBean {
    private static final Logger log = LoggerFactory.getLogger(DataSourceConfig.class);
    @Autowired
    ZkProps zkProps;
    @Autowired
    DataSourceProps dataSourceProps;
	@Autowired
	CuratorFramework curatorFramework;
    /**
     * 数据源map
     * key:dbType_ip_servicename
     * value:DataSource
     */
    public static Map<Object, Object> dataSourceMap = new HashMap<>();
    /**
     * 动态数据源
     */
    public static DynamicDataSource dynamicDataSource = new DynamicDataSource();
    /**
     * 默认数据源
     */
//	public static String DEFAULT_DATASOURCE_TYPE = "SqlServer"+"_"+"BaseUrl"+"_"+"BaseData";
    public static String DEFAULT_DATASOURCE_TYPE = "mysql";

    @Bean(name = "BaseData")
//	@ConfigurationProperties(prefix = "spring.datasource")// application.properteis中对应属性的前缀
    public DataSource dataSourceAllo_dcloud() {
        log.info("默认数据源为{}", "BaseData");
		HikariConfig hikariConfig = new HikariConfig();
		hikariConfig.setDriverClassName(ConstantDbZkPath.MYSQL_DIVER_CLASS);
		hikariConfig.setUsername(dataSourceProps.getUsername());
		hikariConfig.setPassword(dataSourceProps.getPassword());
		hikariConfig.setJdbcUrl(dataSourceProps.getUrl());

        HikariDataSource newHikariDataSource = new HikariDataSource(hikariConfig);

		dynamicDataSource.setDefaultTargetDataSource(newHikariDataSource);
		dataSourceMap.put(DEFAULT_DATASOURCE_TYPE, newHikariDataSource);
		dynamicDataSource.setTargetDataSources(dataSourceMap);
		return dynamicDataSource;
//        return newHikariDataSource;
    }

//    @Bean(name = "dynamicDS")
//    @Primary
//    public DynamicDataSource dataSource() {
//        dynamicDataSource.setDefaultTargetDataSource(dataSourceAllo_dcloud());
//        dataSourceMap.put(DEFAULT_DATASOURCE_TYPE, dataSourceAllo_dcloud());
//        dynamicDataSource.setTargetDataSources(dataSourceMap);
//        return dynamicDataSource;
//    }

    /**
     * 是否存在当前数据库信息的数据源
     *
     * @param dsKey
     * @return true:存在 false:不存在
     */
    public static boolean hasCurrentDataSource(String dsKey) {
        return dataSourceMap.containsKey(dsKey);
    }

	@Override
	public void afterPropertiesSet() throws Exception {
		//TODO 为数据库节点添加监听，当数据发生变化时，改变数据源的信息；
		final NodeCache nodeCache = new NodeCache(curatorFramework, ConstantDbZkPath.DB_ZK_PATH, false);
		nodeCache.getListenable().addListener(() -> {
			System.out.println(ConstantDbZkPath.DB_ZK_PATH + "节点数据发生变化：" + nodeCache.getCurrentData());
			ChildData childData = nodeCache.getCurrentData();
			String db = new String(childData.getData());
			System.out.println("//the new db:" + db);
			changeDb(db);
		});
		//如果为true则首次不会缓存节点内容到cache中，默认为false,设置为true首次不会触发监听事件
		try {
			nodeCache.start(true);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void changeDb(String db) {
		DataSourceProps dataSourceProps = JSON.parseObject(db, DataSourceProps.class);

		HikariDataSource oldHikariDataSource = (HikariDataSource)dataSourceMap.get(DEFAULT_DATASOURCE_TYPE);
		oldHikariDataSource.close();

		HikariDataSource newHikariDataSource = new HikariDataSource();
		newHikariDataSource.setJdbcUrl(dataSourceProps.getUrl());
		newHikariDataSource.setUsername(dataSourceProps.getUsername());
		newHikariDataSource.setPassword(dataSourceProps.getPassword());
		dataSourceMap.put(DEFAULT_DATASOURCE_TYPE, newHikariDataSource);
		dynamicDataSource.afterPropertiesSet();
	}
}
